package v2

import (
	"context"
	"eci-forward/pkg/eci"
	"eci-forward/pkg/logs"
	"eci-forward/pkg/redis"
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
)

// @Summary 创建镜像缓存
// @Description 创建一个新的镜像缓存
// @Tags ECI
// @Accept  multipart/form-data
// @Produce  json
// @Param images formData []string true "镜像列表"
// @Param department_name formData string true "部门名称" Enums(sil, cloud)
// @Param force formData bool false "是否强制重建镜像预热"
// @Success 200 {object} v2.JsonResPonse
// @Failure 400 {object} v2.JsonResPonse
// @Failure 500 {object} v2.JsonResPonse
// @Router /v2/create_image_cache [post]
func ECICreateImageCache(c *gin.Context) {
	images := c.PostFormArray("images")
	departmentName := c.PostForm("department_name")
	force, _ := strconv.ParseBool(c.DefaultPostForm("force", "false"))

	if len(images) == 0 {
		c.JSON(http.StatusBadRequest, gin.H{
			"message":          "images can not be empty",
			"image_cache_name": "",
		})
		return
	}
	if departmentName == "" {
		c.JSON(http.StatusBadRequest, gin.H{
			"message":          "department_name can not be empty",
			"image_cache_name": "",
		})
		return
	}
	key := redis.BuildRedisKey(departmentName, images)
	// if force is true, delete cache
	if force {
		logs.Logger.Info("force is true, skip cahce check")
		redis.GetClient().Del(context.Background(), key)
	}
	// try get cahce
	imageCacheName, err := redis.GetClient().Get(context.Background(), key).Result()
	if err == nil {
		c.JSON(http.StatusOK, gin.H{
			"message":          "hit cache",
			"image_cache_name": imageCacheName,
		})
		return
	} else if err != redis.Nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"message":          "Redis error",
			"image_cache_name": "",
		})
		return
	}
	// missing cache, begin create imagecache
	// get lock
	lockKey := "lock:" + key
	lockSuccess, err := redis.GetClient().SetNX(context.Background(), lockKey, 1, 30*time.Second).Result()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"message":          "Failed to acquire lock",
			"image_cache_name": "",
		})
		return
	}
	if !lockSuccess {
		c.JSON(http.StatusTooManyRequests, gin.H{
			"message":          "Request in process, please try again later",
			"image_cache_name": "",
		})
		return
	}
	defer redis.GetClient().Del(context.Background(), lockKey)
	// recheck cache, maybe other request has created cache
	imageCacheName, err = redis.GetClient().Get(context.Background(), key).Result()
	if err == nil {
		c.JSON(http.StatusOK, gin.H{
			"message":          "success",
			"image_cache_name": imageCacheName,
		})
		return
	} else if err != redis.Nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"message":          "Redis error",
			"image_cache_name": "",
		})
		return
	}

	// create imagecache
	imageCacheName, err = eci.CreateImageCache(departmentName, &images)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"message":          err.Error(),
			"image_cache_name": "",
		})
		return
	}

	_, err = redis.GetClient().Set(context.Background(), key, imageCacheName, 0).Result()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{
			"message":          err.Error(),
			"image_cache_name": imageCacheName,
		})
		return
	}
	c.JSON(http.StatusOK, gin.H{
		"message":          "success",
		"image_cache_name": imageCacheName,
	})
}

// @Summary 查询镜像缓存
// @Description 获取指定部门的镜像缓存信息
// @Tags ECI
// @Accept  json
// @Produce  json
// @Param image_cache_name query string false "镜像缓存名称"
// @Param department_name query string true "部门名称" Enums(sil, cloud)
// @Success 200 {object} v2.JsonResPonse
// @Failure 400 {object} v2.JsonResPonse
// @Failure 500 {object} v2.JsonResPonse
// @Router /v2/describe_image_caches [get]
func ECIDescribeImageCaches(c *gin.Context) {
	imageCacheName := c.Query("image_cache_name")
	departmentName := c.Query("department_name")
	if imageCacheName == "" {
		logs.Logger.Info("image_cache_name is empty, describe all image caches")
	}
	if departmentName == "" {
		c.JSON(400, gin.H{
			"message": "department_name can not be empty",
		})
		return
	}
	res, err := eci.DescribeImageCachesWithImageCacheName(departmentName, imageCacheName)
	if err != nil {
		c.JSON(500, gin.H{
			"message": err.Error(),
			"data":    nil,
		})
		return
	}
	c.JSON(200, gin.H{
		"message": "success",
		"data":    res,
	})
}
